from contextlib import asynccontextmanager
from collections.abc import AsyncIterator
from fastapi_limiter import FastAPILimiter
import redis.asyncio as redis
from fastapi import FastAPI
from fastapi_cache import FastAPICache
from fastapi_cache.backends.redis import RedisBackend
from redis import asyncio as aioredis
from core import Events
from core.Config import settings

REDIS_HOST = settings.REDIS_HOST
REDIS_PORT = settings.REDIS_PORT
REDIS_LIMIT_DB = settings.REDIS_LIMIT_DB
REDIS_CHACE_DB = settings.REDIS_CHACE_DB

@asynccontextmanager
async def limiter_lifespan(_: FastAPI):
    sys_cache_pool = aioredis.ConnectionPool.from_url(
        f"redis://{REDIS_HOST}:{REDIS_PORT}",
        db=REDIS_LIMIT_DB,
        encoding='utf-8',
        decode_responses=False
    )
    redis = aioredis.Redis(connection_pool=sys_cache_pool)
    await FastAPILimiter.init(redis)
    yield
    await FastAPILimiter.close()

@asynccontextmanager
async def cache_lifespan(_: FastAPI) -> AsyncIterator[None]:
    sys_cache_pool = aioredis.ConnectionPool.from_url(
        f"redis://{REDIS_HOST}:{REDIS_PORT}",
        db=REDIS_CHACE_DB,
        encoding='utf-8',
        decode_responses=False
    )
    redis = aioredis.Redis(connection_pool=sys_cache_pool)
    FastAPICache.init(RedisBackend(redis), prefix="cache")
    yield



@asynccontextmanager
async def combined_lifespan(app: FastAPI):
    await Events.startup(app)()
    try:
        async with limiter_lifespan(app):
            async with cache_lifespan(app):
                yield
    finally:
        await Events.stopping(app)()